#posib() API.pm - Written by Matthew Caswell
#posib() Date: January 02, 2013
#posib() ------------
#posib() PrlServerAPI Copyright Matthew Caswell, 2013
#posib() ------------
#posib() This module contains the PrlServerAPI port functions.

package PrlServer::API;

use strict;
use warnings 'all';
use Exporter 'import';
use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS );
use Socket;

$VERSION = 0.01;

@ISA = qw( Exporter );
@EXPORT = ();
@EXPORT_OK = qw( $API_release );
%EXPORT_TAGS = (DEFAULT => [ qw( $API_release ) ]);

our $API_release = "J14";

sub new{
  my($namespace, %args) = @_;
  
  print $args{ip};
  my $class = {
    serverProtocol => (getprotobyname($args{proto}))[2],
    serverHost => $args{host},
    serverPort => $args{port},
    ipOfServer => inet_aton ($args{ip}),
    debug => 0
  };
  
  bless $class, 'PrlServer::API';
  
  return $class;
}

sub createServer{
  my($self) = shift;

  $self->debug ("createServer-socket ();");
  socket ($self->{SOCKET}, PF_INET, SOCK_STREAM, $self->{serverProtocol})
    or die "Can't open socket: $!\n";
    
  $self->debug ("createServer-setsockopt ()\n");
  setsockopt ($self->{SOCKET}, SOL_SOCKET, SO_REUSEADDR, 1)
    or die "Can't set socket SO_REUSEADDR: $!\n";
    
  $self->debug ("createServer-bind ()\n");
  bind ($self->{SOCKET}, sockaddr_in ($self->{serverPort}, $self->{ipOfServer}))
    or die "Couldn't bind to port: $!\n";
    
  $self->debug ("createServer-listen ()\n");
  listen ($self->{SOCKET}, 5)
    or die "Listen: $!\n";
}

sub serverPortIn{
  my($this) = shift;
  
  $this->debug ("serverPortIn-accept ()\n");
  my $clientAddress = accept (NET_SOCKET, $this->{SOCKET});
  
  $this->debug ("serverPortIn-read\n");
  my $acceptReturned;
  while(<NET_SOCKET>){
    $acceptReturned .= $_;
  }
  
  $this->debug ("serverPortIn-close ()\n");
  close (NET_SOCKET);
  $this->debug ("serverPortIn-return ()\n");
  return $acceptReturned;
}

sub serverPortOut{
  my($this, $data) = @_;
  
  $this->debug ("serverPortOut-accept ()\n");
  my $clientAddress = accept (NET_SOCKET, $this->{SOCKET});
  
  $this->debug ("serverPortOut-print ()\n");
  print NET_SOCKET $data;
  
  $this->debug ("serverPortOut-close ()\n");
  close (NET_SOCKET);
}

sub clientPortIn{
  my($this) = shift;
  
  $this->debug ("clientPortIn-socket ()\n");
  socket ($this->{SOCKET}, PF_INET, SOCK_STREAM, $this->{serverProtocol})
    or die "Couldn't socket () : $!\n";
    
  $this->debug ("clientPortIn-connect ()\n");
  connect ($this->{SOCKET}, sockaddr_in ($this->{serverPort}, $this->{ipOfServer}))
    or die "Couldn't connect: $!\n";
  
  my $socket = $this->{SOCKET};
  
  my $bytes; 
  
  while(<$socket>){
    $bytes .= $_;
  }
  
  $this->debug ("clientPortIn-close ()\n");
  close ($this->{SOCKET});
  
  $this->debug ("clientPortIn-return ()\n");
  return $bytes;
}

sub clientPortOut{
  my($this, $data) = @_;
  
  $this->debug ("clientPortOut-socket ()\n");
  socket ($this->{SOCKET}, PF_INET, SOCK_STREAM, $this->{serverProtocol})
    or die "Couldn't socket () : $!\n";
    
  $this->debug ("clientPortOut-connect ()\n");
  connect ($this->{SOCKET}, sockaddr_in ($this->{serverPort}, $this->{ipOfServer}))
    or die "Couldn't connect () : $!\n";
    
  $this->debug ("clientPortOut-print ($data)\n");
  print {$this->{SOCKET}} $data;
  
  $this->debug ("clientPortOut-close ()\n");
  close ($this->{SOCKET});
}

sub debug{
  my($this, $dbg) = @_;
  
  print STDERR $dbg if $this->{debug} == 1;
}

sub debugOff{
  my($this) = shift;
  
  $this->{debug} = 0;
}

sub debugOn{
  my($this) = shift;
  
  $this->{debug} = 1;
}

1;
